﻿#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

//用队列实现栈
//https://leetcode.cn/problems/implement-stack-using-queues/description/
typedef int QDataType;
//定义队列结点的结构
typedef struct QueueNode
{
	QDataType data;
	struct QueueNode* next;
}QueueNode;

//定义队列的结构
typedef struct Queue
{
	QueueNode* phead;  //队头
	QueueNode* ptail;  //队尾
	int size;          //队列有效元素个数
}Queue;

void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newnode == NULL)
	{
		perror("malloc fail!\n");
		exit(1);
	}
	newnode->data = x;
	newnode->next = NULL;

	//队列为空，队头和队尾都是newnode
	if (pq->phead == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else {
		//pq->ptail newnode
		pq->ptail->next = newnode;
		pq->ptail = pq->ptail->next;
	}
	pq->size++;
}

//队列判空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->phead == NULL;
}
//队列有效元素个数
int QueueSize(Queue* pq)
{

	return pq->size;
}
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	//只有一个结点
	if (pq->phead == pq->ptail)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else {
		//多个结点
		QueueNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
	--pq->size;
}
//取队头数据
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->phead->data;
}
//取队尾数据
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->ptail->data;
}
//销毁队列
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QueueNode* pcur = pq->phead;
	while (pcur)
	{
		QueueNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}


typedef struct {
	Queue s1;
	Queue s2;
} MyStack;


MyStack* myStackCreate() {
	MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
	QueueInit(&obj->s1);
	QueueInit(&obj->s2);
	return obj;
}

void myStackPush(MyStack* obj, int x) {
	if (!QueueEmpty(&obj->s1))
	{
		QueuePush(&obj->s1, x);

	}
	else 
	{
		QueuePush(&obj->s2, x);

	}
}

//typedef struct Queue
//{
//	QueueNode* phead;  //队头
//	QueueNode* ptail;  //队尾
//	int size;          //队列有效元素个数
//}Queue;
int myStackPop(MyStack* obj) {
	Queue* emp = &obj->s2;
	Queue* full = &obj->s1;
	if (!QueueEmpty(&obj->s2))
	{
		emp = &obj->s1;
		full = &obj->s2;
	}
	
	while (full->size > 1)
	{
		QueuePush(emp, QueueFront(full));
		QueuePop(full);

	}
	int num = QueueBack(full);
	QueuePop(full);
	return num;
}

int myStackTop(MyStack* obj) {

	if (!QueueEmpty(&obj->s1))
	{
		return QueueBack(&obj->s1);

	}
	else
	{
		return QueueBack(&obj->s2);

	}

}	

bool myStackEmpty(MyStack* obj) {
	return QueueEmpty(&obj->s1) && QueueEmpty(&obj->s2);
}

void myStackFree(MyStack* obj) {
	
	QueueDestroy(&obj->s1);
	QueueDestroy(&obj->s2);
	free(obj);
}




//.用栈实现队列
//https://leetcode.cn/problems/implement-queue-using-stacks/description/
typedef int STDataType;
//定义栈的数据结构
typedef struct Stack
{
	STDataType* arr;
	int top;          //指向栈顶位置
	int capacity;     //容量
}ST;

void STInit(ST* ps)
{
	assert(ps);
	ps->arr = NULL;
	ps->top = ps->capacity = 0;
}
void STDestroy(ST* ps)
{
	if (ps->arr != NULL)
		free(ps->arr);

	ps->arr = NULL;
	ps->top = ps->capacity = 0;
}
//入栈--栈顶
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		//空间满了--增容
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDataType* tmp = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!\n");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
	//空间足够
	ps->arr[ps->top++] = x;
}
//栈是否为空
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}
//出栈--栈顶
void StackPop(ST* ps)
{
	assert(!StackEmpty(ps));
	--ps->top;
}
//取栈顶元素
STDataType StackTop(ST* ps)
{
	assert(!StackEmpty(ps));
	return ps->arr[ps->top - 1];
}
//获取栈中有效元素个数
int STSize(ST* ps)
{
	assert(ps);
	return ps->top;
}


typedef struct {
	ST s1;
	ST s2;
} MyQueue;


MyQueue* myQueueCreate() {
	MyQueue* obj = malloc(sizeof(MyQueue));
	STInit(&obj->s1);
	STInit(&obj->s2);
	return obj;
}

void myQueuePush(MyQueue* obj, int x) {
	
	
	StackPush(&obj->s1, x);
	
}

int myQueuePop(MyQueue* obj) {
	if (StackEmpty(&obj->s2))
	{
		while (!StackEmpty(&obj->s1))
		{
		
			StackPush(&obj->s2, StackTop(&obj->s1));
			StackPop(&obj->s1);
		}
		int num = StackTop(&obj->s2);
		StackPop(&obj->s2);
		return num;
	}
	int num = StackTop(&obj->s2);
	StackPop(&obj->s2);
	return num;

}

int myQueuePeek(MyQueue* obj) {
	if (StackEmpty(&obj->s2))
	{
		while (!StackEmpty(&obj->s1))
		{

			StackPush(&obj->s2, StackTop(&obj->s1));
			StackPop(&obj->s1);
		}
		int num = StackTop(&obj->s2);
	
		return num;
	}
	int num = StackTop(&obj->s2);
	return num;

}

bool myQueueEmpty(MyQueue* obj) {
	return StackEmpty(&obj->s2) && StackEmpty(&obj->s1);
}

void myQueueFree(MyQueue* obj) {

	STDestroy(&obj->s2);
	STDestroy(&obj->s1);
	free(obj);
}



//设计循环队列

//https://leetcode.cn/problems/design-circular-queue/

typedef int QDataType;
//定义队列结点的结构


typedef struct {
	QDataType* arr;
	int phead;  //队头
	int ptail;  //队尾
	int cap;          //队列有效元素个数
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {

	MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
	obj->arr = (QDataType*)malloc(sizeof(QDataType) * (k + 1));
	obj->cap = k;
	obj->phead = obj->ptail = 0;
	return obj;
}


bool myCircularQueueIsEmpty(MyCircularQueue* obj) {

	return obj->ptail == obj->phead;

}

bool myCircularQueueIsFull(MyCircularQueue* obj) {

	return ((obj->ptail + 1) % (obj->cap + 1)) == obj->phead;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
	if (myCircularQueueIsFull(obj))
	{
		return false;
	}
	obj->arr[obj->ptail] = value;
	obj->ptail++;
	obj->ptail %= (obj->cap + 1);
	return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
	if (myCircularQueueIsEmpty(obj))
	{
		return false;
	}
	obj->phead++;
	obj->phead %= (obj->cap + 1);
	
	return true;

}

int myCircularQueueFront(MyCircularQueue* obj) {

	if (myCircularQueueIsEmpty(obj))
	{
		return -1;
	}

	return obj->arr[obj->phead];
}

int myCircularQueueRear(MyCircularQueue* obj) {
	if (myCircularQueueIsEmpty(obj))
	{
		
		return -1;
	}
	int index = obj->ptail - 1;
	if (obj->ptail == 0)
	{
		index = obj->cap;
	}
	return obj->arr[index];
}



void myCircularQueueFree(MyCircularQueue* obj) {
	free(obj->arr);
	free(obj);
}



